﻿namespace Probel.Ldoc.ViewModels.Pages
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.IO.Compression;
    using System.Linq;
    using System.Windows.Input;

    using Probel.Ldoc.Services.Dto;
    using Probel.Ldoc.Services.Services;
    using Probel.Mvvm.DataBinding;

    public class ExtractPicturesViewModel : BaseViewModel
    {
        #region Fields

        private readonly ICommand extractCommand;
        private readonly IPatientService Service;

        private int maximum = 100;
        private int progress = 0;
        private string zipPath;

        #endregion Fields

        #region Constructors

        public ExtractPicturesViewModel(IErrorService errorService, IPatientService service, bool isAsync = true)
            : base(errorService, isAsync)
        {
            this.Service = service;
            this.extractCommand = new RelayCommand(Extract);

            this.ZipPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        }

        #endregion Constructors

        #region Events

        public event EventHandler Extracted;

        #endregion Events

        #region Properties

        public ICommand ExtractCommand
        {
            get { return this.extractCommand; }
        }

        public int Maximum
        {
            get { return this.maximum; }
            set
            {
                this.maximum = value;
                this.OnPropertyChanged(() => Maximum);
            }
        }

        public int Progress
        {
            get { return this.progress; }
            set
            {
                this.progress = value;
                this.OnPropertyChanged(() => Progress);
            }
        }

        public string ZipPath
        {
            get { return this.zipPath; }
            set
            {
                this.zipPath = value;
                this.OnPropertyChanged(() => ZipPath);
            }
        }

        #endregion Properties

        #region Methods

        private void Extract()
        {
            this.Progress = 0;
            this.Async(() => this.ExtractAsync(),
                       () => this.OnExtracted());
        }

        private void ExtractAsync()
        {
            var pics = this.Service.GetAllPictures();
            this.Maximum = (pics.Count() * 2) + 40;
            this.Progress = 20;

            using (var zip = new FileStream(Path.Combine(this.ZipPath, "Data.zip"), FileMode.Create))
            using (var archive = new ZipArchive(zip, ZipArchiveMode.Update))
            {
                foreach (var pic in pics)
                {
                    this.Progress++;
                    ZipArchiveEntry entry = archive.CreateEntry(GetFileName(pic), CompressionLevel.NoCompression);
                    using (var writer = new BinaryWriter(entry.Open()))
                    {
                        writer.Write(pic.Bitmap);
                    }

                    this.Progress++;
                    ZipArchiveEntry entryThumb = archive.CreateEntry(GetThumbName(pic), CompressionLevel.NoCompression);
                    using (var writer = new BinaryWriter(entryThumb.Open()))
                    {
                        writer.Write(pic.ThumbnailBitmap);
                    }
                }
            }
            this.Progress += 20;
        }

        private string GetFileName(PictureDto pic)
        {
            return string.Format("{0}_{1}.jpg", pic.IdPatient, pic.Id);
        }

        private string GetThumbName(PictureDto pic)
        {
            return string.Format("thumb_{0}_{1}.jpg", pic.IdPatient, pic.Id);
        }

        private void OnExtracted()
        {
            if (this.Extracted != null)
            {
                this.Extracted(this, EventArgs.Empty);
            }
        }

        #endregion Methods
    }
}